home *** CD-ROM | disk | FTP | other *** search
- /*
- Sherlock initialization routines.
-
- source: sl_init.c
- started: November 4, 1993.
- version:
- February 5, 1996.
- Added support for Symantec C.
- September 26, 1995.
- log_open now takes only one argument.
- January 7, 1994.
- */
-
- #include <LIBlib.h>
-
- #include <sl.h>
- #include <sl2.h>
-
- #include <LIBenv.h>
- #include <LIBlog.h>
- #include <LIBmem.h>
-
- #if defined(THINK_C) || defined(SYMANTEC_C) || defined(__MWERKS__)
- #include <mac_gui.h>
- #endif
-
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
-
- /*
- Globals initialized by this module...
- */
-
- /*
- The call stack.
- */
- sl_snode * sl_stack = NULL; /* Dynamically allocated. */
- int sl_level = 0; /* Stack pointer. */
- int sl_lmax = 0; /* Max stack pointer. */
-
- /*
- The hash table.
- */
- sl_node ** sl_htab = NULL;
-
- /*
- The wildcard list.
- */
- sl_node * sl_wcard = NULL; /* Head of wildcard list. */
-
- /*
- The "check" name of the current macro.
- */
- char * sl_cname = NULL; /* The "check" name of current macro. */
-
- /*
- The local and global disable counts.
- */
- long sl_ldisable = 0; /* Local disable count. */
- long sl_gdisable = 0; /* Global disable count. */
-
- /*
- Global flags.
-
- sl_troff is TRUE initially to avoid trouble if Sherlock
- macros are called before SL_INIT is called.
- */
- bool sl_troff = TRUE; /* TRUE: all tracing disabled. */
- bool sl_nodots = FALSE; /* TRUE: no level dots. */
- bool sl_warning = TRUE; /* TRUE: warn about negative time. */
- bool sl_full_trace = FALSE; /* TRUE: make STATB the same as TICKB. */
-
- long sl_neg_count = 0; /* Number of negative times. */
- int sl_node_count = 0; /* Allocated nodes. */
-
- #if defined(THINK_C) || defined(SYMANTEC_C) || defined(__MWERKS__)
- UnsignedWide sl_wide_time;
- #endif
-
-
- /*
- Variables local to this file.
- */
- static bool init_flag = FALSE; /* Sherlock inited flag. */
- static sl_node *node_table = NULL; /* Dynamically allocated. */
- static bool signon_flag = FALSE; /* TRUE: the signon message has been printed. */
-
- /*
- Function prototypes of internal routines.
- */
- static int sl_prefix (char *, char *);
- static void sl_set (char *, int);
-
- /*
- Enable Sherlock macros initially.
- */
- void
- sl_go(void)
- {
- if (!init_flag) {
- sl_troff = FALSE;
- init_flag = TRUE;
- }
- }
-
- /*
- SL_INIT macro--Initialize the statistics routines.
- */
- void
- sl_init(char * version)
- {
- /*
- Allocate Sherlock's tables.
- Nothing bad happens sl_init is called twice.
- */
- if (node_table == NULL) {
-
- node_table = lib_calloc( (size_t) SL_MAX_NODES, sizeof(sl_node));
- sl_stack = lib_calloc( (size_t) SL_MAX_STACK, sizeof(sl_snode));
- sl_htab = lib_calloc( (size_t) SL_MAX_HASH, sizeof(sl_node *));
-
- if (node_table == NULL || sl_stack == NULL || sl_htab == NULL) {
- sl_abort(SL_ABORT_INIT);
- }
- }
-
- /* Set size of initial stack area. */
- #if 0 // defined(THINK_C) // doesn't work on PowerPc
- sl_min_margin = sl_margin_start = env_stackMargin();
- #endif
-
- /* 7/17/89: indicate that we are starting to initialize. */
- sl_troff = FALSE;
-
- if (strcmp(version, SL_VERSION_NAME) != 0) {
- es("sl_init: Header version "); es(version);
- es(" does not match run-time version: ");
- es(SL_VERSION_NAME); enl();
- sl_exit();
- }
-
- /*
- PC only code:
-
- Initialize the interrupt vectors. See prf.asm.
- */
- #if defined(TURBOC) || defined(MICRO_SOFT)
- sl_von();
- DEBUG(es("Trap vectors installed.\n"));
- #endif
- }
-
- /*
- Return TRUE if string s1 matches string s2 with wildcards possible in
- string s1.
-
- The string s2 may start with '-', which inhibits wildcard matches.
- */
- int
- sl_match(register char *s1, register char *s2)
- {
- register char c;
-
- /* '-' inhibits wildcard matches. */
- if (*s2 == '-') {
- return FALSE;
- }
-
- for (;;) {
- c = *s1++;
- if (c == '\0') {
- return !*s2;
- }
- else if (c == '*') {
- /* Matches zero or more characters. */
- return TRUE;
- }
- else if (c == '?') {
- /* Matches exactly one character. */
- if (*s2 == '\0') {
- return FALSE;
- }
- else {
- s2++;
- }
- }
- else if (c != *s2++) {
- return FALSE;
- }
- }
- }
-
- /*
- Allocate a new node for tracepoint s from the static node table.
-
- If a match is found from the wildcard list, use that value for tracing.
- Otherwise, set the tracing field to zero (FALSE).
- */
- sl_node *
- sl_new(char *s)
- {
- register sl_node * node, *p;
-
- if (node_table == NULL) {
- sl_abort(SL_ABORT_NEW);
- }
-
- /* Not found. Point node at a new node. */
- if (sl_node_count >= SL_MAX_NODES) {
- es("sl_new: trace table overflow\n");
- sl_exit();
- }
-
- /* Create the new node. */
- node = node_table + sl_node_count;
- sl_node_count++;
- node -> name = s;
- node -> calls = 0;
-
- /*
- Search the wildcard list for a node which matches s.
- If found. Set trace field.
- */
- for (p = sl_wcard; p; p = p -> next) {
- if (sl_match(p -> name, s)) {
- node -> trace = (p -> trace) ? ((p -> trace) | SL_WILD_BIT) : 0;
- return node;
- }
- }
-
- /* No match. */
- node -> trace = 0;
- return node;
- }
-
- /*
- SL_OFF macro.
- Turn tracing off for one variable or a class of variables.
- */
- void
- sl_off(char *s)
- {
- if (strcmp(s, "sl_trace")==0) {
- ecnl(); es("Disabling ALL tracing...\n");
- sl_troff = TRUE;
- return;
- }
- if (strcmp(s, "sl_dots")==0) {
- ecnl(); es("Disabling level dots...\n");
- sl_nodots = TRUE;
- return;
- }
- if (strcmp(s, "sl_time")==0) {
- ecnl(); es("Disabling time reporting...\n");
- sl_time_flag = FALSE;
- return;
- }
- if (strcmp(s, "sl_warning")==0) {
- ecnl(); es("Disabling negative time warning...\n");
- sl_warning = FALSE;
- return;
- }
-
- if (!signon_flag) {
- sl_signon();
- }
- es("Disabling trace of "); es(s); enl();
-
- sl_cname = "TRACE_OFF";
- sl_set(s, 0);
- }
-
- /*
- SL_ON macro.
- Turn tracing on for one variable or a class of variables.
- */
- void
- sl_on(char *s)
- {
- /* BUG FIX to V1.5 */
- if (sl_troff && sl_match(s, "trace")) {
- es("Revoking --trace...\n");
- es("WARNING: this may generate call stack underflows.\n");
- sl_troff = FALSE;
- return;
- }
- if (strcmp(s, "sl_full_trace")==0) {
- ecnl(); es("Tracing statb macros...\n");
- sl_full_trace = TRUE;
- return;
- }
-
- /*
- ++>>file_name opens file_name.
-
- We want to sign on just *after* the ++>> arg opening the log file,
- and we will assume the ++>> arg is the first arg.
- */
-
- if (*s == '>' && *(s+1) == '>') {
-
- /* 9/26/95: log_open now takes only one argument. */
- log_open(s+2);
- if (!signon_flag) {
- sl_signon();
- }
- }
- else {
- if (!signon_flag) {
- sl_signon();
- }
- es("Enabling trace of "); es(s); enl();
-
- sl_cname = "TRACE_ON";
- sl_set(s, 1);
- }
- }
-
- /*
- SL_PARSE macro--Parse the command list.
- argcp points to the argc count.
- argv contains pointers to the arguments.
- on_str and off_str are the on_prefix and off_prefix respectively.
- */
- void
- sl_parse(argcp, argv, on_str, off_str)
- int *argcp; char **argv; char *on_str; char *off_str;
- {
- char ** base;
- char * arg;
- int argc;
- size_t on_len, off_len;
-
- on_len = strlen(on_str);
- off_len = strlen(off_str);
-
- argc = *argcp;
- argc--;
- argv++;
- base = argv;
- while (argc-- > 0) {
- arg = *argv++;
-
- /* 8/8/89: Protect against over-run user error. */
- if (arg == 0L) {
- es("Warning: argc argument to SL_PARSE too big\n");
- return;
- }
-
- if (sl_prefix(on_str, arg)) {
- if (!*(arg + on_len)) {
- es("Warning: lone "); es(on_str); enl();
- sl_exit();
- }
- sl_on(arg + on_len);
-
- /* One less argument for the program. */
- (*argcp)--;
- }
- else if (sl_prefix(off_str, arg)) {
- if (!*(arg + off_len)) {
- es("Warning: lone "); es(off_str); enl();
- sl_exit();
- }
- sl_off(arg + off_len);
-
- /* One less argument for the program. */
- (*argcp)--;
-
- }
- else {
- /* Compact original argv vector. */
- *base++ = arg;
- }
- }
-
- /* 2/25/92 */
- *base++ = NULL;
- if (!signon_flag) {
- sl_signon();
- }
- ecnl();
- }
-
- /*
- Return TRUE if string p is a prefix of string s.
- */
- static int
- sl_prefix(char *p, char *s)
- {
- while (*p) {
- if (*p++ != *s++) {
- return FALSE;
- }
- }
- return TRUE;
- }
-
- /*
- Update the tracing status for string s and set the disable flags.
- Enable tracing if flag is TRUE.
-
- If s contains a wildcard, ALL nodes matching s have their enable
- field set to flag and a new entry for s is added to the wild card list.
- Otherwise, the single node (if it exists) which matches s has its
- enable field set to flag.
- */
- static void
- sl_set(char *s, int flag)
- {
- sl_node * p = NULL;
-
- /* Be very careful. */
- if (sl_htab == NULL) {
- return;
- }
-
- sl_check(s);
- if (!sl_wild(s)) {
-
- /* No wild card. Just set one flag. */
- p = sl_find("SL_ON, SL_OFF or SL_PARSE", s);
- p -> trace = flag;
- return;
- }
-
- /* Search ALL hash lists. */
- {
- register int i;
- for (i = 0; i < SL_MAX_HASH; i++) {
-
- for (p = sl_htab [i]; p; p = p -> next) {
-
- /* Bug fix: 4/19/89 wildcards possible only in first arg. */
- if (sl_match(s, p -> name)) {
-
- /* Set the wild bit only if p -> trace is not already on. */
- if (p -> trace) {
- p -> trace = flag;
- }
- else {
- p -> trace = flag ? (SL_TRACE_BIT | SL_WILD_BIT) : 0;
- }
- }
- }
- }
- }
-
- /*
- Add new element at the head of the wildcard list.
- This will supercede any previous conflicting entries.
- */
- p = sl_new(s);
- p -> next = sl_wcard;
- sl_wcard = p;
- p -> trace = flag;
- return;
- }
-
- /*
- Sign on.
- */
- void
- sl_signon(void)
- {
- /* Sign on. */
- es("Sherlock support routines: "); es(SL_VERSION_NAME); es(".\n");
- signon_flag = TRUE;
- }
-
- /*
- Return TRUE if string s1 contains a wildcard character, i.e., an
- asterisk or a question mark.
- */
- int
- sl_wild(register char *s)
- {
- register char c;
-
- for (;;) {
- c = *s++;
- if (c == '\0') {
- return FALSE;
- }
- else if (c == '*' || c == '?') {
- return TRUE;
- }
- }
- }
-
-